/*
 * Texture.cpp
 *
 *  Created on: Apr 18, 2009
 *      Author: Ry
 */

#ifdef WIN32
#include <windows.h>
#endif

#include <GL/glew.h>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <iostream>
#include <string>

#include "Texture.h"
#include "exceptions.h"

using namespace std;

Texture::Texture(std::string texturePath, bool mipmaps) {
	file = texturePath;
	this->mipmaps = mipmaps;
	load(texturePath, mipmaps);
}

void Texture::reload() {
	if (glIsTexture(handle) == GL_TRUE)
		glDeleteTextures(1, &handle);
	load(file, mipmaps);
}

void Texture::load(std::string texturePath, bool mipmaps) {
	SDL_Surface *surface = NULL;
	surface = IMG_Load(texturePath.c_str());

	if(!surface)
		throw FileException(texturePath);

	GLint format;
	unsigned int r = surface->format->Rshift;
	unsigned int g = surface->format->Gshift;
	unsigned int b = surface->format->Bshift;
	unsigned int a = surface->format->Ashift;

	if (r == 0 && g == 8 && b == 16 && a > 0)
		format = GL_RGBA;
	else if (r == 0 && g == 8 && b == 16 && a == 0)
		format = GL_RGB;
	else
		throw GameException("Unrecognized color format.");

	// Have OpenGL generate a texture name
	glGenTextures(1, &handle);

	// Create the texture
	glBindTexture(GL_TEXTURE_2D, handle);
	glTexImage2D(GL_TEXTURE_2D,
			0,
			surface->format->BytesPerPixel,
			surface->w,
			surface->h,
			0,
			format,
			GL_UNSIGNED_BYTE,
			surface->pixels);

	if (mipmaps) {
		gluBuild2DMipmaps(GL_TEXTURE_2D, 4, surface->w, surface->h, format, GL_UNSIGNED_BYTE, surface->pixels);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	} else {
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	}

	// Don't want to keep this texture in system RAM.
	SDL_FreeSurface(surface);
}

void Texture::use(){
	glBindTexture(GL_TEXTURE_2D, handle);
}

Texture::~Texture() {
	if (glIsTexture(handle) == GL_TRUE)
		glDeleteTextures(1, &handle);
}
